package com.yuanxin.chooseimage.zxing;

import android.Manifest;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.google.zxing.Result;
import com.google.zxing.client.result.ParsedResult;
import com.google.zxing.client.result.ResultParser;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.AndPermission;
import com.yanzhenjie.permission.Permission;
import com.yuanxin.chooseimage.R;
import com.yuanxin.chooseimage.zxing.camera.CameraManager;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Create by WangGao at 2018/3/20
 */
public class ScanErCodeManager extends ViewGroupManager<ScanErCodeView> implements SurfaceHolder.Callback ,LifecycleEventListener{

    private static String TAG = "ScanErCodeManager";

    private static final long BULK_MODE_SCAN_DELAY_MS = 1000L;


    private CameraManager cameraManager;
    private CaptureActivityHandler handler;
    private ViewfinderView viewfinderView;
    private boolean hasSurface;
    private InactivityTimer inactivityTimer;
    private BeepManager beepManager;
    //光线感应控制闪光灯不稳定，屏蔽了
    //private AmbientLightManager ambientLightManager;
    private ThemedReactContext reactContext;

    public ThemedReactContext getContext() {
        return reactContext;
    }

    public ViewfinderView getViewfinderView() {
        return viewfinderView;
    }

    public Handler getHandler() {
        return handler;
    }

    CameraManager getCameraManager() {
        return cameraManager;
    }

    private ScanErCodeView view;

    @Override
    public String getName() {
        return "ScanCodeView";
    }

    private final int start = 1;
    private final int stop = 2;
    //闪光灯使用AmbientLightManager控制，因此废弃这两个方法
    @Deprecated
    private final int flashOpen = 3;
    @Deprecated
    private final int flashClose = 4;
    private final int restart = 5;


    @Override
    protected ScanErCodeView createViewInstance(final ThemedReactContext reactContext) {
        this.reactContext = reactContext;
        view = new ScanErCodeView(reactContext);
        PreferenceManager.setDefaultValues(reactContext, R.xml.qrcode_preferences, true);
        reactContext.addLifecycleEventListener(this);
        hasSurface = false;
        inactivityTimer = new InactivityTimer(reactContext.getCurrentActivity());
        beepManager = new BeepManager(reactContext.getCurrentActivity());
        //ambientLightManager = new AmbientLightManager(reactContext);
        cameraManager = new CameraManager(reactContext.getCurrentActivity().getApplication());
        viewfinderView = (ViewfinderView) view.findViewById(R.id.viewfinder_view_scan);
        handler = null;
        onHostResume();
        AndPermission.with(getContext())
                .permission(Permission.CAMERA)
                .onGranted(new Action() {
                    @Override
                    public void onAction(List<String> permissions) {
                        try {
                            onHostResume();
                        }
                        catch (Exception ex){
                            Toast.makeText(getContext(),"申请相机权限失败，请进入手机设置界面手动授权。",Toast.LENGTH_LONG).show();
                            ex.printStackTrace();
                        }
                    }
                })
                .onDenied(new Action() {
                    @Override
                    public void onAction(List<String> permissions) {
                        Toast.makeText(getContext(),"申请相机权限失败，请进入手机设置界面手动授权。",Toast.LENGTH_LONG).show();
                        for (int i=0;i<permissions.size();i++){
                           // Log.e(TAG,"拒绝了权限："+permissions.get(i));
                        }
                    }
                }).start();

        return view;
    }

    @Override
    public void onHostResume() {

        resetStatusView();

        beepManager.updatePrefs();
        //ambientLightManager.start(cameraManager);

        inactivityTimer.onResume();

        SurfaceView surfaceView = (SurfaceView) view.findViewById(R.id.preview_view_scan);
        final SurfaceHolder surfaceHolder = surfaceView.getHolder();
        if (hasSurface) {
            initCamera(surfaceHolder);
        } else {
            surfaceHolder.addCallback(this);
        }
    }

    @Override
    public void onHostPause() {
        if (handler != null) {
            handler.quitSynchronously();
            handler = null;
        }
        inactivityTimer.onPause();
        //ambientLightManager.stop();
        beepManager.close();
        cameraManager.closeDriver();
        //historyManager = null; // Keep for onActivityResult
        if (!hasSurface) {
            SurfaceView surfaceView = (SurfaceView) view.findViewById(R.id.preview_view_scan);
            if(surfaceView!=null){
                SurfaceHolder surfaceHolder = surfaceView.getHolder();
                surfaceHolder.removeCallback(this);
            }
        }
    }

    @Override
    public void onHostDestroy() {
        inactivityTimer.shutdown();
    }



    //因为ios有着三个属性，所有安卓也存在，只是没有用到
    private boolean autoStartRunning;
    private String maskViewBackgroundColor;
    private String maskViewBorderColorColor;

    /**
     * 是否进入时自动开启扫描
     */
    @ReactProp(name = "autoStartRunning")
    public void SetAutoStartRunning(ScanErCodeView view, @Nullable boolean autoStartRunning) {
        this.autoStartRunning = autoStartRunning;
       // Log.e(TAG, "autoStartRunning---" + autoStartRunning);
    }

    /**
     * 设置描框的背景颜色
     */
    @ReactProp(name = "maskViewBackgroundColor")
    public void SetMaskViewBackgroundColor(ScanErCodeView view, @Nullable String maskViewBackgroundColor) {
        this.maskViewBackgroundColor = maskViewBackgroundColor;
       // Log.e(TAG, "maskViewBackgroundColor---" + maskViewBackgroundColor);
    }

    /**
     * 设置边框的颜色
     */
    @ReactProp(name = "maskViewBorderColorColor")
    public void SetMaskViewBorderColorColor(ScanErCodeView view, @Nullable String maskViewBorderColorColor) {
        this.maskViewBorderColorColor = maskViewBorderColorColor;
       // Log.e(TAG, "maskViewBorderColorColor---" + maskViewBorderColorColor);
    }

    /*
     * 扫描框的宽高
     */
    @ReactProp(name = "scanSize")
    public void SetScanSize(ScanErCodeView view, @Nullable ReadableMap autoStartRunning) {

        int width = autoStartRunning.getInt("width");
        int height = autoStartRunning.getInt("height");
        int w = dip2px(reactContext, width);
        int h = dip2px(reactContext, height);
        viewfinderView.setScanWidth(w);
        viewfinderView.setScanHeight(h);

    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public static int dip2px(ReactContext context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
     */
    public static int px2dip(ReactContext context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * 打开扫描
     */
    public void start(ScanErCodeView view) {
       // Log.i(TAG, "start");
        onHostResume();
    }

    /**
     * 关闭当前照像机
     */
    public void stop(ScanErCodeView view) {
       // Log.i(TAG, "stop");
        onHostPause();
        onHostDestroy();
        reactContext.removeLifecycleEventListener(this);
    }

    /**
     * 打开闪光灯
     */
    @Deprecated
    public void flashOpen(ScanErCodeView view) {
       // Log.e(TAG, "flashOpen");
        cameraManager.setTorch(true);
    }

    /**
     * 关闭闪光灯
     */
    @Deprecated
    public void flashClose(ScanErCodeView view) {
       // Log.e(TAG, "flashClose");
        cameraManager.setTorch(false);
    }

    /**
     * 读取到Code 后回调
     */
    public void SetOnCodeRead(ScanErCodeView view, String CodeRead, String type) {
        WritableMap event = Arguments.createMap();
        event.putString("type", type);
        event.putString("data", CodeRead);
        ReactContext reactContext = (ReactContext) view.getContext();
        reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
                view.getId(),
                "onCodeRead",
                event);
    }

    /**
     * 出错时调用的接口
     */
    public void SetOnError(ScanErCodeView view, int code, String error) {
        WritableMap event = Arguments.createMap();
        event.putInt("code", code);
        event.putString("description", error);
        ReactContext reactContext = (ReactContext) view.getContext();
        reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
                view.getId(),
                "onErrorMessage",
                event);
    }

    @Nullable
    @Override
    public Map getExportedCustomDirectEventTypeConstants() {
        return MapBuilder.of(
                "onCodeRead", MapBuilder.of("registrationName", "onCodeRead"),
                "onErrorMessage", MapBuilder.of("registrationName", "onErrorMessage")
        );
    }

    @Nullable
    @Override
    public Map<String, Integer> getCommandsMap() {
        return MapBuilder.of(
                "start", start,
                "stop", stop,
                "flashOpen", flashOpen,
                "flashClose", flashClose,
                "restart", restart
        );
    }

    @Override
    public void receiveCommand(ScanErCodeView root, int commandId, @Nullable ReadableArray args) {
        switch (commandId) {
            case start:
                this.start(root);
                break;
            case stop:
                this.stop(root);
                break;
            case flashOpen:
                this.flashOpen(root);
                break;
            case flashClose:
                this.flashClose(root);
                break;
            case restart:
                this.restart();
                break;
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
       // Log.d(TAG,"surfaceCreated");
        if (!hasSurface) {
            hasSurface = true;
            onHostResume();
        }
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
       // Log.d(TAG,"surfaceChanged");
        if (!hasSurface) {
            hasSurface = true;
            onHostResume();
        }
    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
       // Log.d(TAG,"surfaceDestroyed");
        hasSurface = false;
        onHostPause();
        onHostDestroy();
    }

    /**
     * A valid barcode has been found, so give an indication of success and show the results.
     *
     * @param rawResult The contents of the barcode.
     */
    public void handleDecode(Result rawResult) {
        inactivityTimer.onActivity();
        if (rawResult != null) {
            ParsedResult parsedResult = parseResult(rawResult);
            SetOnCodeRead(view, rawResult.getText(), parsedResult.getType().name());
            beepManager.playBeepSoundAndVibrate();
        } else {
            SetOnError(view, -1, "result is null");
        }
    }

    private ParsedResult parseResult(Result rawResult) {
        return ResultParser.parseResult(rawResult);
    }

    private void initCamera(SurfaceHolder surfaceHolder) {
        if (surfaceHolder == null) {
            throw new IllegalStateException("No SurfaceHolder provided");
        }
        if (cameraManager.isOpen()) {
           // Log.w(TAG, "initCamera() while already open -- late SurfaceView callback?");
            return;
        }
        try {
            cameraManager.openDriver(surfaceHolder);
            // Creating the handler starts the preview, which can also throw a RuntimeException.
            if (handler == null) {
                handler = new CaptureActivityHandler(this);
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
           // Log.w(TAG, ioe);
        } catch (RuntimeException e) {
            e.printStackTrace();
            // Barcode Scanner has seen crashes in the wild of this variety:
            // java.?lang.?RuntimeException: Fail to connect to camera service
           // Log.w(TAG, "Unexpected error initializing camera", e);
        }
    }

    //重新开始扫描
    public void restart() {
        if (handler != null) {
            handler.sendEmptyMessageDelayed(Constants.restart_preview, BULK_MODE_SCAN_DELAY_MS);
        }
        resetStatusView();
    }

    private void resetStatusView() {
        viewfinderView.setVisibility(View.VISIBLE);
    }

    public void drawViewfinder() {
        viewfinderView.drawViewfinder();
    }

}
